package edu.winona.csclub.testing.gui;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import edu.winona.csclub.testing.core.ConfigFile;
import edu.winona.csclub.testing.core.Result;
import edu.winona.csclub.testing.core.Test;
import edu.winona.csclub.testing.core.TestCase;
import edu.winona.csclub.testing.core.TestHarness;
import edu.winona.csclub.testing.generators.EnumProvider;
import edu.winona.csclub.testing.generators.TestCaseGenerator;
import edu.winona.csclub.testing.gui.html.HTMLGenerator;
import edu.winona.csclub.testing.gui.imageExport.JpegTestEncoder;
import edu.winona.csclub.testing.utils.FileSystem;

public class TestInterfaceInternalFrame extends JInternalFrame implements ActionListener, ListSelectionListener {

	private ConfigFile configFile;
	
	static final int xOffset = 30, yOffset = 30;
	
	static int openFrameCount = 0;
	private TestsView testView;
	private JList cases;

	private JSplitPane splitPane;

	private List<TestCase> testCases= new LinkedList<TestCase>();
		
	public TestInterfaceInternalFrame(ConfigFile cf ){
	
        super("Test #" + (++openFrameCount),true,true,true,true);
        configFile = cf;
        
        this.setLayout(new FlowLayout());
        cases = new JList(new String[]{""});
        cases.setCellRenderer(new TestCaseListCellRenderer());
        cases.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        cases.setSelectedIndex(0);
        cases.addListSelectionListener(this);
        
        JScrollPane listScrollPane = new JScrollPane(cases);
        
        testView=new TestsView(null);
       
        JPanel right = new JPanel();
        right.setLayout(new BorderLayout());
        right.add(new JLabel("Tests",JLabel.CENTER),BorderLayout.PAGE_START);
        right.add(testView,BorderLayout.CENTER);

      //Create a split pane with the two scroll panes in it.
      splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                                 listScrollPane, right);
      splitPane.setOneTouchExpandable(false);
      splitPane.setDividerLocation(100);
      this.add(splitPane);
        this.setJMenuBar(createMenu());
          setSize(630,500);
          setLocation(xOffset*openFrameCount, yOffset*openFrameCount);
          this.setVisible(true);
	}


	private JMenuBar createMenu() {
        JMenuBar menuBar = new JMenuBar();

        //Set up the lone menu.
        JMenu menu = new JMenu("Test Suite");
        menu.setMnemonic(KeyEvent.VK_T);
        
        JMenu run = new JMenu("Run");
        menu.setMnemonic(KeyEvent.VK_U);

        JMenu export = new JMenu("Export");
        
        menuBar.add(menu);
        menuBar.add(run);
        menuBar.add(export);

        JMenuItem menuItem = new JMenuItem("New Test Case");
        menuItem.setMnemonic(KeyEvent.VK_N);
        menuItem.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_N, ActionEvent.ALT_MASK));
        menuItem.setActionCommand("newTestCase");
        menuItem.addActionListener(this);
        menu.add(menuItem);

        menuItem = new JMenuItem("Save");
        menuItem.setMnemonic(KeyEvent.VK_S);
        menuItem.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_S, ActionEvent.ALT_MASK));
        menuItem.setActionCommand("load");
        menuItem.addActionListener(this);
        menu.add(menuItem);
        
        menuItem = new JMenuItem("Close");
        menuItem.setMnemonic(KeyEvent.VK_C);
        menuItem.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_C, ActionEvent.ALT_MASK));
        menuItem.setActionCommand("dispose");
        menuItem.addActionListener(this);
        menu.add(menuItem);

        
        JMenuItem runa = new JMenuItem("Run all");
        runa.setMnemonic(KeyEvent.VK_A);
        runa.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_A, ActionEvent.ALT_MASK));
        runa.setActionCommand("runAll");
        runa.addActionListener(this);
        run.add(runa);
        
        JMenuItem runs = new JMenuItem("Run selected");
        runs.setMnemonic(KeyEvent.VK_R);
        runs.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_R, ActionEvent.ALT_MASK));
        runs.setActionCommand("runSelected");
        runs.addActionListener(this);
        run.add(runs);
        
        JMenuItem j = new JMenuItem("Export to JPEG");
        j.setMnemonic(KeyEvent.VK_J);
        j.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_J, ActionEvent.ALT_MASK));
        j.setActionCommand("jpegExport");
        j.addActionListener(this);
        export.add(j);
        
        JMenuItem H = new JMenuItem("Export to HTML");
        H.setMnemonic(KeyEvent.VK_H);
        H.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_H, ActionEvent.ALT_MASK));
        H.setActionCommand("htmlExport");
        H.addActionListener(this);
        export.add(H);
        
        return menuBar;
	}


	public void jpegExport(){
		try {
			JpegTestEncoder.save(this.testView);
		} catch (IOException e) {
			JOptionPane.showMessageDialog(this, e.getMessage());
		}
	}
	
	public void htmlExport(){
		try {
			HTMLGenerator.save(this.testView);
		} catch (IOException e) {
			JOptionPane.showMessageDialog(this, e.getMessage());
		}
	}
	
	public void actionPerformed(ActionEvent e) {
		try{
			Method m = this.getClass().getMethod(e.getActionCommand(), new Class[]{});
			m.invoke(this,new Object[]{});
			}catch(Exception ex){
				ex.printStackTrace();
			}
	}
	
	public void newTestCase(){
		HashMap<String,Class> sc = FileSystem.getLocalEnumProviders();
		String s =(String) JOptionPane.showInputDialog(null, "Select test case generator", "New Test Case", JOptionPane.QUESTION_MESSAGE, new ImageIcon(), sc.keySet().toArray(), sc.keySet().toArray()[0]);
		Class gen = sc.get(s);
		EnumProvider ep=null;
		try {
			if( gen.getConstructors()[0].getParameterTypes().length > 0 ){
				Object[] options = {"Normal", "Robust"};
				int n = JOptionPane.showOptionDialog(null,
					    "What type of "+s+" would you like?",
					    "Robust vs Normal",
					    JOptionPane.YES_NO_OPTION,  JOptionPane.QUESTION_MESSAGE,  null, options, options[0]);
				
				boolean res = n != JOptionPane.YES_OPTION;
				
				ep = (EnumProvider)gen.getConstructors()[0].newInstance( res );
				
			} else {
				ep=(EnumProvider) gen.newInstance();
			}
			TestCase ts = TestCaseGenerator.GenerateEnumTestCases(configFile, ep);
			ts.setName(s);
			testCases.add(ts);
			cases.setListData(testCases.toArray());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}


	public void runAll(){
		for(Test t : testView.getTests() ){
			Result r = TestHarness.execute( t, 1000000 );
			testView.result.put(t, r);
			testView.updateUI();
		}
	}
	
	public void runSelected(){
		Test t = testView.getSelectedTest();
		Result r = TestHarness.execute( t, 1000000 );
		testView.result.put(t, r);
		testView.updateUI();
	}
	
	public void valueChanged(ListSelectionEvent e) {
		testView.update( (TestCase) cases.getSelectedValue() );
	}
	public void paint(Graphics g ){
		splitPane.setSize(this.getSize());
		super.paint(g);
		
	}
}
